package com.ruoyi.system.utils;

import com.ruoyi.common.exception.ServiceException;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class SerialNumberChecker {
    /**
     * 检查号码是否符合格式要求
     * @param number 要检查的号码
     * @return 如果符合格式要求返回 true，否则返回 false
     */
    public static boolean isValidNumber(String number) {
        if (number.length() != 10) {
            return false;
        }
        if (number.charAt(0) != 'J') {
            return false;
        }
        for (int i = 1; i < 10; i++) {
            if (!Character.isDigit(number.charAt(i))) {
                return false;
            }
        }
        return true;
    }


    // 验证单个号码是否符合基本格式（长度为 10，首字符为 'J'，后续 9 个为数字）
    private static boolean isValidFormat(String number) {
        if (number.length() != 10) {
            return false;
        }
        if (number.charAt(0) != 'J') {
            return false;
        }
        for (int i = 1; i < 10; i++) {
            if (!Character.isDigit(number.charAt(i))) {
                return false;
            }
        }
        return true;
    }

    private static void checkNumber(String startNumber){
        // 检查字符串长度是否为 10
        if (startNumber.length() != 10) {
            throw new ServiceException("输入的号码长度必须为 10");
        }
        // 检查第一个字符是否为 'J'
        if (startNumber.charAt(0) != 'J') {
            throw new ServiceException("输入的号码第一个字符必须为 'J'");
        }
        // 检查后续 9 个字符是否为数字
        for (int i = 1; i < 10; i++) {
            if (!Character.isDigit(startNumber.charAt(i))) {
                throw new ServiceException("输入的号码从第二个字符起必须为数字");
            }
        }
    }

    /**
     * 判断并生成完整的标十号码
     * @param startNumber 起始号码
     * @return 完整的标十号码数组
     * @throws ServiceException 如果号码不符合标十规则
     */
    public static String[] checkAndGenerateSerialNumbers(String startNumber) {
        checkNumber(startNumber);
        // 检查尾号是否为 1
        if (startNumber.charAt(9) != '1') {
            throw new ServiceException("输入的号码尾号不是 1，不符合标十规则");
        }

        String[] result = new String[10];
        result[0] = startNumber;

        // 提取出数字部分
        long numberPart = Long.parseLong(startNumber.substring(1));
        for (int i = 1; i < 10; i++) {
            numberPart++;
            // 确保生成的数字部分长度为 9 位，不足则前面补 0
            String formattedNumber = String.format("%09d", numberPart);
            result[i] = "J" + formattedNumber;
        }
        // 检查最后一个号码的尾号是否为 0
        if (result[9].charAt(9) != '0') {
            throw new ServiceException("生成的最后一个号码尾号不是 0，不符合标十规则");
        }
        return result;
    }

    /**
     * 判断并生成完整的标百号码
     * @param startNumber 起始号码
     * @return 完整的标百号码数组
     * @throws ServiceException 如果号码不符合标百规则
     */
    public static String[] checkAndGenerateSerialHundreds(String startNumber) {
        checkNumber(startNumber);
        // 检查尾部两位是否为 01
        if (!startNumber.endsWith("01")) {
            throw new ServiceException("输入的号码尾部两位不是 01，不符合标百规则");
        }

        String[] result = new String[100];
        result[0] = startNumber;

        // 提取出数字部分
        long numberPart = Long.parseLong(startNumber.substring(1));
        for (int i = 1; i < 100; i++) {
            numberPart++;
            // 确保生成的数字部分长度为 9 位，不足则前面补 0
            String formattedNumber = String.format("%09d", numberPart);
            result[i] = "J" + formattedNumber;
        }
        // 检查最后一个号码的尾部两位是否为 00
        if (!result[99].endsWith("00")) {
            throw new ServiceException("生成的最后一个号码尾部两位不是 00，不符合标百规则");
        }
        return result;
    }


    /**
     * 生成两个号码之间的连续号
     * @param startNumber 起始号码
     * @param endNumber 结束号码
     * @return 包含连续号的列表
     * @throws ServiceException 如果输入的号码不符合格式要求或起始号码大于结束号码
     */
    public static List<String> generateConsecutiveNumbers(String startNumber, String endNumber) {
        checkNumber(startNumber);
        checkNumber(endNumber);

        // 提取数字部分并转换为长整型
        long startNum = Long.parseLong(startNumber.substring(1));
        long endNum = Long.parseLong(endNumber.substring(1));

        // 检查起始号码是否大于结束号码
        if (startNum > endNum) {
            throw new ServiceException("起始号码不能大于结束号码。");
        }

        List<String> consecutiveNumbers = new ArrayList<>();
        for (long i = startNum; i <= endNum; i++) {
            // 确保生成的数字部分长度为 9 位，不足则前面补 0
            String formattedNumber = String.format("%09d", i);
            consecutiveNumbers.add("J" + formattedNumber);
        }
        return consecutiveNumbers;
    }


    // 验证 10 个号码是否符合标十规则
    public static boolean validateTenNumbers(List<String> numbers) {
        if (numbers.size() != 10) {
            return false;
        }

        // 过滤掉不符合基本格式的号码
        List<String> validNumbers = new ArrayList<>();
        for (String number : numbers) {
            if (isValidFormat(number)) {
                validNumbers.add(number);
            }
        }
        if (validNumbers.size() != 10) {
            return false;
        }

        // 对符合基本格式的号码进行排序
        Collections.sort(validNumbers);

        // 找到尾号为 1 的号码作为起始号码
        String startNumber = null;
        for (String number : validNumbers) {
            if (number.charAt(9) == '1') {
                startNumber = number;
                break;
            }
        }
        if (startNumber == null) {
            return false;
        }

        // 提取起始号码的前缀和数字部分
        String prefix = startNumber.substring(0, 9);
        long startNum = Long.parseLong(startNumber.substring(1));

        // 验证后续号码是否连续
        for (int i = 0; i < 10; i++) {
            String currentNumber = validNumbers.get(i);
            long expectedNum = startNum + i;
            String expectedPrefix = String.format("J%09d", expectedNum).substring(0, 9);
            if (!expectedPrefix.equals(prefix)) {
                // 处理进位后前缀变化的情况
                prefix = expectedPrefix;
            }
            if (!currentNumber.startsWith(prefix)) {
                return false;
            }
            long actualNum = Long.parseLong(currentNumber.substring(1));
            if (actualNum != expectedNum) {
                return false;
            }
        }

        // 验证最后一个号码尾号是否为 0
        String lastNumber = validNumbers.get(9);
        return lastNumber.charAt(9) == '0';
    }


    // 验证 100 个号码是否符合标百规则
    public static boolean validateHundredNumbers(List<String> numbers) {
        if (numbers.size() != 100) {
            return false;
        }

        // 过滤掉不符合基本格式的号码
        List<String> validNumbers = new ArrayList<>();
        for (String number : numbers) {
            if (isValidFormat(number)) {
                validNumbers.add(number);
            }
        }
        if (validNumbers.size() != 100) {
            return false;
        }

        // 对符合基本格式的号码进行排序
        Collections.sort(validNumbers);

        // 找到尾部两位为 01 的号码作为起始号码
        String startNumber = null;
        for (String number : validNumbers) {
            if (number.endsWith("01")) {
                startNumber = number;
                break;
            }
        }
        if (startNumber == null) {
            return false;
        }

        // 提取起始号码的数字部分
        long startNum = Long.parseLong(startNumber.substring(1));

        // 验证后续号码是否连续
        for (int i = 0; i < 100; i++) {
            String currentNumber = validNumbers.get(i);
            long expectedNum = startNum + i;
            String expectedNumber = "J" + String.format("%09d", expectedNum);
            if (!currentNumber.equals(expectedNumber)) {
                return false;
            }
        }

        // 验证最后一个号码尾部两位是否为 00
        String lastNumber = validNumbers.get(99);
        return lastNumber.endsWith("00");
    }


    // 验证一串号码是否为连续号
    public static boolean isConsecutiveNumbers(List<String> numbers) {
        if (numbers.size() < 2) {
            return false;
        }

        // 过滤掉不符合基本格式的号码
        List<String> validNumbers = new ArrayList<>();
        for (String number : numbers) {
            if (isValidFormat(number)) {
                validNumbers.add(number);
            }
        }
        if (validNumbers.size() != numbers.size()) {
            return false;
        }

        // 对符合基本格式的号码进行排序
        Collections.sort(validNumbers);

        // 提取第一个号码的数字部分
        long prevNum = Long.parseLong(validNumbers.get(0).substring(1));

        // 验证后续号码是否连续
        for (int i = 1; i < validNumbers.size(); i++) {
            long currentNum = Long.parseLong(validNumbers.get(i).substring(1));
            if (currentNum != prevNum + 1) {
                return false;
            }
            prevNum = currentNum;
        }

        return true;
    }
    /**
     * 检查号码是否为靓号
     * @param number 要检查的号码
     * @return 如果是靓号返回 true，否则返回 false
     */
    public static boolean isLuckyNumber(String number) {
        if (!isValidNumber(number)) {
            return false;
        }
        String numPart = number.substring(1);
        return !numPart.contains("3") && !numPart.contains("4") && !numPart.contains("7");
    }

    // 验证单个号码是否为靓号（前 8 位不包含 3、4、7）
    private static boolean isLuckyNumberByIndex(String number, int index) {
        String prefix = number.substring(1, index);
        return !prefix.contains("3") && !prefix.contains("4") && !prefix.contains("7");
    }

    // 验证 10 个号码是否为靓号标十
    public static boolean isLuckyStandardTen(List<String> numbers) {
        for (String number : numbers) {
            if (!isLuckyNumberByIndex(number,9)) {
                return false;
            }
        }
        return true;
    }

    // 验证 100 个号码是否为靓号标百
    public static boolean isLuckyStandardTens(List<String> numbers) {
        for (String number : numbers) {
            if (!isLuckyNumberByIndex(number,8)) {
                return false;
            }
        }
        return true;
    }



}